/**
 ********************************************************************************
 *
 *文件名称：
 *
 *文件日期：
 *
 *文件描述：
 *
 *文件版本：
 *
 *修改历史：
 *
 ********************************************************************************
 ***/

/*******************************	头文件包含区	**********************************/
#include "eeprom.h"

/******************************* 全局变量定义区 **********************************/
u8 p_flash_data[P_SIZE] = {0};
/**
 *********************************************************************************
 *
 *函数名称：
 *
 *函数参数：无
 *
 *函数返回值：无
 *
 *功能描述：
 *
 *********************************************************************************
 **/
uint8_t
FlashWrite(uint32_t start_addr, uint16_t *pbuf, uint16_t plen)
{
	u8 ret = 1;
	ret = flashProgram(start_addr, (u32)pbuf, plen * 2);
	return ret;
}

/**
 *********************************************************************************
 *
 *函数名称：
 *
 *函数参数：无
 *
 *函数返回值：无
 *
 *功能描述：
 *
 *********************************************************************************
 **/
uint16_t FlashRead(uint32_t addr)
{
	return *(__IO uint16_t *)(addr);
}
/**
 *********************************************************************************
 *
 *函数名称：
 *
 *函数参数：无
 *
 *函数返回值：无
 *
 *功能描述：
 *
 *********************************************************************************
 **/
uint8_t FlashReadALL(uint32_t start_addr, uint16_t *pOutBuf, uint16_t OutBufLen)
{
	volatile uint32_t i = 0;

	for (i = 0; i < OutBufLen; i++)
	{
		pOutBuf[i] = FlashRead(start_addr + i * 2);
	}
	return 1;
}

uint8_t FlashReadALLU8(uint32_t start_addr, uint8_t *pOutBuf, uint16_t OutBufLen)
{
	volatile uint32_t i = 0;

	for (i = 0; i < OutBufLen; i++)
	{
		pOutBuf[i] = *(__IO uint8_t *)(start_addr + i);
	}
	return 1;
}
/**
 *********************************************************************************
 *
 *函数名称：
 *
 *函数参数：无
 *
 *函数返回值：无
 *
 *功能描述：
 *
 *********************************************************************************
 **/
#if 0
u8 FlashErase(uint32_t addr, uint16_t sector_num)
{
	uint32_t i, sectorError = 0, sector_addr = 0;

	//sector_addr = addr / 8192;
	sector_addr = addr / 4096;

	for (i = 0; i < sector_num; i++)
	{
		WDT->EN = 0xbb;
		sectorError = flashSectorErase(sector_addr + i);
		if (sectorError != 0)
			return sectorError;
	}
	return sectorError;
}
#else
u8 FlashErase(uint32_t addr, uint16_t sector_num)
{
	uint32_t i, sectorError = 0, sector_addr = 0;

	// sector_addr = addr / 8192;
	sector_addr = addr / 128;

	for (i = 0; i < sector_num; i++)
	{
		WDT->EN = 0xbb;
		sectorError = flashPageErase(sector_addr + i);
		if (sectorError != 0)
			return sectorError;
	}
	return sectorError;
}
#endif

/**
 *********************************************************************************
 *
 *函数名称：
 *
 *函数参数：无
 *
 *函数返回值：无
 *
 *功能描述：
 *
 *********************************************************************************
 **/
void data_flash_write(void)
{
	uint16_t crc;
	u8 ret = 1,i = 0;
	regStruct Read_reg;

	uint16_t   crc_16;

	ret = ret;
	if((reg.R.v / 10) > 60)
	{
		
		if (reg.RW.ota_flag == 2)
			return; // OTA升级包不保存
		LOGD("Write flash!\r\n");
		crc = crc16((uint8_t *)&reg, sizeof(reg) - 2);
		reg.crc16.crc16_h = crc >> 8;
		reg.crc16.crc16_l = crc & 0x00ff;
		
		ret = eeprom_program(ALARM_REMAP_ADDR, (uint32_t)&ALARM_R, sizeof(ALARM_R));
		ret = eeprom_program(LAMP_POWER, (uint32_t)&power, sizeof(power));
	
		for(i = 0; i < 3; i++)
		{
			ret = eeprom_program(DEV_INFO_ADDR, (uint32_t)&reg, sizeof(reg));
			
			ret = FlashReadALL(DEV_INFO_ADDR, (uint16_t *)&Read_reg, sizeof(Read_reg) / 2);
			crc = crc16((uint8_t *)&Read_reg, sizeof(Read_reg) - 2);
			crc_16 = ((uint16_t)Read_reg.crc16.crc16_h << 8) + Read_reg.crc16.crc16_l;

			if (crc == crc_16)
			{
				//LOGD("CRC SUS!\r\n");
				return;
			}
			else
			{
				LOGD("CRC Fail!\r\n");
			}	
		}
		
	}
	else
	{
		LOGD("reg.R.v ERR \r\n");
	}
}

/**
 *********************************************************************************
 *
 *函数名称：
 *
 *函数参数：无
 *
 *函数返回值：无
 *
 *功能描述：
 *
 *********************************************************************************
 **/
void data_flash_read(uint16_t time_out)
{
	volatile uint16_t i = time_out, crc, crc_16, ret;
	uint32_t data[20] = {0}; 

	while (i--)
	{
		delay_ms(5);
		WDT->EN = 0xbb;
		ret = FlashReadALL(DEV_INFO_ADDR, (uint16_t *)&reg, sizeof(reg) / 2);
		crc = crc16((uint8_t *)&reg, sizeof(reg) - 2);
		crc_16 = ((uint16_t)reg.crc16.crc16_h << 8) + reg.crc16.crc16_l;
		
		ret = FlashReadALL(ALARM_REMAP_ADDR, (uint16_t *)&ALARM_R, sizeof(ALARM_R) / 2);

		ret = FlashReadALL(LAMP_POWER, (uint16_t *)&power, sizeof(power) / 2);

		ret = FlashReadALL(POWER_OFF_ADDR, (uint16_t *)&data, sizeof(data) / 2);
		reg.W.lamp1_power_on_timestamp 	= data[0];
		reg.W.lamp1_power_off_timestamp = data[1];
		LOGD("\r\nlamp1_power_off_timestamp:%u\r\n", reg.W.lamp1_power_off_timestamp);
		reg.W.lamp2_power_on_timestamp = data[2];
		reg.W.lamp2_power_off_timestamp = data[3];
	

		if (crc == crc_16)
			return;
	}
	param_init();
	data_flash_write();
	LOGD("Parameter read failed!\r\n");
}

/**
 *********************************************************************************
 *
 *函数名称：
 *
 *函数参数：无
 *
 *函数返回值：无
 *
 *功能描述：
 *
 *********************************************************************************
 **/
void IAP_APP_Jump(void)
{
	//#define APP_ADDR 0x0000F000
	uint32_t JumpAddr;

	void (*pFun)(void);
	__disable_irq(); //关中断
	JumpAddr = *(__IO uint32_t *)(FLASH_OTA_ADDR + 4);

	__set_MSP(*(__IO uint32_t *)FLASH_OTA_ADDR);

	pFun = (void (*)(void))JumpAddr;

	(*pFun)();
}
/**
 *********************************************************************************
 *
 *函数名称：
 *
 *函数参数：无
 *
 *函数返回值：无
 *
 *功能描述：
 *
 *********************************************************************************
 **/
u8 eeprom_earse(uint32_t earse_addr, uint32_t len)
{
	uint32_t i, for_i = len / P_SIZE;
	u8 ret = 1;
	memset(p_flash_data, 0xff, sizeof(p_flash_data));
	for (i = 0; i < for_i; i++)
	{
		WDT->EN = 0xbb;
		ret = eeprom_program(earse_addr + i * P_SIZE, (u32)p_flash_data, P_SIZE);
		if (ret)
			return ret;
	}
	return ret;
}
/**
 *********************************************************************************
 *
 *函数名称：
 *
 *函数参数：无
 *
 *函数返回值：无
 *
 *功能描述：
 *
 *********************************************************************************
 **/
u8 eeprom_program(uint32_t dst_addr, uint32_t src_addr, uint32_t len)
{
	u8 ret = 1, count = 0;
	do
	{
		ret = eepromProgram(dst_addr, src_addr, len);
		if (ret)
		{
			delay_ms(1);
			WDT->EN = 0xbb;
		}
	} while (ret && (count++) < 10);

	if (ret)
		LOGD("eeprom error:ret:%d", ret);

	SysTick_Config(73728);
	return ret;
}
/**
 *********************************************************************************
 *
 *函数名称：
 *
 *函数参数：无
 *
 *函数返回值：无
 *
 *功能描述：
 *
 *********************************************************************************
 **/
u8 flash_program(uint32_t dst_addr, uint32_t src_addr, uint32_t len)
{
	u8 ret = 1, count = 0;
	do
	{
		ret = flashProgram(dst_addr, src_addr, len);
		if (ret)
		{
			delay_ms(1);
			WDT->EN = 0xbb;
		}
	} while (ret && (count++) < 10);

	if (ret)
		LOGD("flash error:ret:%d", ret);
	return ret;
}
/**
 *********************************************************************************
 *
 *函数名称：
 *
 *函数参数：无
 *
 *函数返回值：无
 *
 *功能描述：
 *
 *********************************************************************************
 **/

void IAP_IAP_Jump(void)
{
#define IAP_ADDR 0x00000000
	uint32_t JumpAddr;

	void (*pFun)(void);
	__disable_irq(); //关中断
	JumpAddr = *(__IO uint32_t *)(IAP_ADDR + 4);

	__set_MSP(*(__IO uint32_t *)IAP_ADDR);

	pFun = (void (*)(void))JumpAddr;

	(*pFun)();
}


void save_power_off_data(void)
{
	uint32_t 	data[20] = {0};
	static 	uint8_t flag = 0;

	if((reg.R.v / 10) < 60 && flag == 0)
	{
		check_lamp_sw(0, 0, leakDete.system_run_timestamp);
		data[0] = reg.W.lamp1_power_on_timestamp;
		data[1] = reg.W.lamp1_power_off_timestamp;
		data[2] = reg.W.lamp2_power_on_timestamp;
		data[3] = reg.W.lamp2_power_off_timestamp;
		LOGD("\r\n lamp1_power_off_timestamp:%u\r\n", reg.W.lamp1_power_off_timestamp);
		data[19] = crc16((uint8_t *)&data, sizeof(data) - 4);
		eeprom_program(POWER_OFF_ADDR, (uint32_t)&data, sizeof(data));

		flag = 1;
	}

}

